package com.ecoolex.union.pay.retailer.core.manager;

import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.union.pay.retailer.core.dao.UnionPayCouponDAO;
import com.ecoolex.union.pay.retailer.core.util.UnionPayCouponSecureService;
import com.ecoolex.union.pay.retailer.core.util.unionpay.LogUtil;
import com.ecoolex.union.pay.retailer.entity.UnionPayCoupon;
import com.ecoolex.union.pay.retailer.entity.UnionPayCoupon.Column;
import com.ecoolex.union.pay.retailer.entity.UnionPayCouponExample;
import com.ecoolex.union.pay.retailer.enums.UnionPayCouponOperateType;
import com.ecoolex.union.pay.retailer.enums.UnionPayCouponStatus;
import com.ecoolex.union.pay.retailer.pojo.UnionPayCouponOperateRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UnionPayCouponManager {
    @Autowired
    private UnionPayCouponDAO dao;

    @Autowired
    UnionPayCouponSecureService unionPayCouponSecureService;

    @Autowired
    private UnionPayCouponVerifyingConsumptionManager unionPayCouponVerifyingConsumptionManager;



    /**
     * 获取所有用户银联优惠券
     * @param userId 用户ID
     * @return
     */
    public Pagination<UnionPayCoupon> getCouponsByUserId(Integer userId, @NonNull Page page) {
        List<Integer> list = new ArrayList<>(2);
        list.add(UnionPayCouponStatus.USED.real());
        list.add(UnionPayCouponStatus.INVALID.real());
        UnionPayCouponExample example = new UnionPayCouponExample();
        UnionPayCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(UnionPayCoupon.NOT_DELETED) //
                .andStatusNotIn(list)
                .andUserIdEqualTo(userId);
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());
        example.orderBy(UnionPayCoupon.Column.endEffectiveTime.desc());
        return Pagination.create(page,
                dao.countByExample(example),
                () -> dao.selectByExample(example));
    }

    public List<UnionPayCoupon> getCouponsByUserId(Integer userId) {
        List<Integer> list = new ArrayList<>(2);
        list.add(UnionPayCouponStatus.USED.real());
        list.add(UnionPayCouponStatus.INVALID.real());
        UnionPayCouponExample example = new UnionPayCouponExample();
        UnionPayCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(UnionPayCoupon.NOT_DELETED) //
                .andStatusNotIn(list)
                .andUserIdEqualTo(userId);
        example.orderBy(UnionPayCoupon.Column.endEffectiveTime.desc());
        return dao.selectByExample(example);
    }

    /**
     * 获取用户指定的银联券
     * @param userId
     * @param couponId
     * @param status
     * @return
     */
    public UnionPayCoupon getCouponByUserId(Integer userId, Integer couponId, UnionPayCouponStatus... status){
        List<Integer> __status = Arrays.stream(status).map(UnionPayCouponStatus::real).collect(Collectors.toList());
        LogUtil.writeLog(String.format("USERID:%s,COUPONID:%s,STATUS:%s",userId,couponId, __status));
        UnionPayCouponExample example = new UnionPayCouponExample();
        UnionPayCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(UnionPayCoupon.NOT_DELETED) //
                .andStatusIn(__status) //
                .andUserIdEqualTo(userId)  //
                .andCouponIdEqualTo(couponId);
        return dao.selectOneByExample(example);
    }

    /**
     * 检查优惠券是否已存在
     * @param couponCode
     * @return
     */
    public List<UnionPayCoupon> checkCouponExists(String couponCode, Integer userId){
        List<Integer> status = Arrays.asList(UnionPayCouponStatus.UNUSED.real(),UnionPayCouponStatus.LOCKED.real());
        UnionPayCouponExample example = new UnionPayCouponExample();
        UnionPayCouponExample.Criteria criteria = example.createCriteria();
        criteria.andStatusIn(status) //
                .andDeletedEqualTo(UnionPayCoupon.NOT_DELETED) //
                .andUserIdEqualTo(userId)
                .andCouponCodeEqualTo(couponCode);
        return dao.selectByExample(example);
    }

    /**
     * 作废优惠券
     * @param unionPayCoupon 作废优惠券
     */
    public void invalid(UnionPayCoupon unionPayCoupon){
        unionPayCoupon.setStatus(UnionPayCouponStatus.INVALID.real());
        dao.updateByPrimaryKeySelective(unionPayCoupon,UnionPayCoupon.Column.status);

    }

    public void update(UnionPayCoupon unionPayCoupon) {
        dao.updateByPrimaryKey(unionPayCoupon);
    }

    /**
     * 锁定银联优惠券
     * @param orderNo
     * @param couponId
     * @param transPrice
     * @param userId
     * @param createUser
     */
    public UnionPayCoupon lockUnionPayCoupon(String orderNo, Integer couponId, BigDecimal transPrice, Integer userId, String createUser,String currencyCode) {
        UnionPayCoupon coupon = getCouponByUserId(userId,couponId, UnionPayCouponStatus.UNUSED);
        BizAssert.isTrue(Check.notNull(coupon), ResultCode.VERIFY.build(10), "优惠券不存在");

        BizAssert.isTrue(Check.eq(coupon.getStatus(),UnionPayCouponStatus.UNUSED.real()), ResultCode.VERIFY.build(10), "优惠券不用");

        UnionPayCouponOperateRequest request = new UnionPayCouponOperateRequest();
        request.setProcType(UnionPayCouponOperateType.COUPON_LOCK.real());
        request.setRefNumber(orderNo);
        request.setTransCurr(UnionPayCouponCurrencyCodeManager.translateCurrencyCode(currencyCode));
        request.setTransAmt(transPrice.setScale(2).toPlainString());
        request.setCouponId(coupon.getCouponCode());
        request.setLocalTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        unionPayCouponSecureService.callUnionPayCouponService(request);

        coupon.setUpdateUser(createUser);
        coupon.setUpdateTime(Date.from(Instant.now()));
        coupon.setStatus(UnionPayCouponStatus.LOCKED.real());
        dao.updateByPrimaryKeySelective(coupon, UnionPayCoupon.Column.updateUser, UnionPayCoupon.Column.updateTime, UnionPayCoupon.Column.status);
        return coupon;
    }

    /**
     * 核销银联优惠券
     * @param userId
     * @param couponId
     * @param orderNo
     * @param discount
     * @param createUser
     */
    public UnionPayCoupon verifyUnionPayCoupon(Integer userId, Integer couponId, String orderNo,BigDecimal realPrice, BigDecimal discount, String createUser,String currencyCode) {
        UnionPayCoupon coupon = getCouponByUserId(userId,couponId, UnionPayCouponStatus.LOCKED);
        BizAssert.isTrue(Check.notNull(coupon), ResultCode.VERIFY.build(10), "优惠券不存在");

//        DirectMailGoodsOrder order = directMailGoodsOrderManager.getById(orderId);
//        BizAssert.isTrue(Check.notNull(order), ResultCode.VERIFY.build(10), "订单不存在");

        UnionPayCouponOperateRequest entity = new UnionPayCouponOperateRequest();
        entity.setProcType(UnionPayCouponOperateType.COUPON_VERIFYING.real());
        entity.setRefNumber(orderNo);
        entity.setTransCurr(UnionPayCouponCurrencyCodeManager.translateCurrencyCode(currencyCode));
        entity.setTransAmt(realPrice.add(discount.abs()).setScale(2).toPlainString());
        entity.setCouponId(coupon.getCouponCode());
        entity.setLocalTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        unionPayCouponSecureService.callUnionPayCouponService(entity);

        coupon.setUseTime(Date.from(Instant.now()));
        coupon.setUpdateUser(createUser);
        coupon.setUpdateTime(Date.from(Instant.now()));
        coupon.setStatus(UnionPayCouponStatus.USED.real());
        dao.updateByPrimaryKeySelective(coupon, UnionPayCoupon.Column.useTime, UnionPayCoupon.Column.updateUser, UnionPayCoupon.Column.updateTime,UnionPayCoupon.Column.status);
        //创建银联优惠券核销记录
        unionPayCouponVerifyingConsumptionManager.create(coupon,orderNo,realPrice, createUser);
        return coupon;
    }

    /**
     * 释放银联优惠券
     * @param orderNo
     * @param couponId
     * @param userId
     * @param discount
     * @param createUser
     */
    public UnionPayCoupon releaseUnionPayCoupon(String orderNo,BigDecimal realPrice, Integer couponId, Integer userId, BigDecimal discount, String createUser,String currencyCode) {
        UnionPayCoupon coupon = getCouponByUserId(userId,couponId, UnionPayCouponStatus.LOCKED);
        BizAssert.isTrue(Check.notNull(coupon), ResultCode.VERIFY.build(10), "优惠券不存在");

//        DirectMailGoodsOrder order = directMailGoodsOrderManager.getById(orderId);
//        BizAssert.isTrue(Check.notNull(order), ResultCode.VERIFY.build(10), "订单不存在");

        UnionPayCouponOperateRequest entity = new UnionPayCouponOperateRequest();
        entity.setProcType(UnionPayCouponOperateType.COUPON_UNLOCK.real());
        entity.setRefNumber(orderNo);
        entity.setTransCurr(UnionPayCouponCurrencyCodeManager.translateCurrencyCode(currencyCode));
        entity.setTransAmt(realPrice.add(discount.abs()).setScale(2).toPlainString());
        entity.setCouponId(coupon.getCouponCode());
        entity.setLocalTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        unionPayCouponSecureService.callUnionPayCouponService(entity);

        coupon.setUpdateUser(createUser);
        coupon.setUpdateTime(Date.from(Instant.now()));
        coupon.setStatus(UnionPayCouponStatus.UNUSED.real());
        dao.updateByPrimaryKeySelective(coupon, UnionPayCoupon.Column.updateUser, UnionPayCoupon.Column.updateTime,UnionPayCoupon.Column.status);
        return coupon;
    }

    public UnionPayCoupon receiveUnionPayCoupon(UnionPayCoupon unionPayCoupon) {
        dao.insert(unionPayCoupon);
        return unionPayCoupon;
    }

    /**
     * 获取过期券
     * @param now
     * @param size
     * @return
     */
    public List<UnionPayCoupon> getExpireCoupon(Date now,Integer size){
        List<Integer> status = Arrays.asList(UnionPayCouponStatus.UNUSED.real(),UnionPayCouponStatus.LOCKED.real());
    	UnionPayCouponExample example = new UnionPayCouponExample();
        UnionPayCouponExample.Criteria criteria = example.createCriteria();
        criteria.andStatusIn(status)
        .andEndEffectiveTimeLessThanOrEqualTo(now)
        .andDeletedEqualTo(UnionPayCoupon.NOT_DELETED);
        example.orderBy(Column.endEffectiveTime.asc());
        example.limit(size);
        return dao.selectByExample(example);
    }

    public void expireCoupon(UnionPayCoupon coupon,String updateUser) {
    	coupon.setStatus(UnionPayCouponStatus.EXPIRED.real());
    	coupon.setUpdateUser(updateUser);
    	coupon.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKeySelective(coupon, Column.status,Column.updateUser,Column.updateTime);
    }
}
